﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Linq;
using System.Text;

namespace Dycox.Drawing
{
    public class DiagramShapeCollection : Collection<DiagramShape>
    {
        public event EventHandler CollectionChanged;

        public DiagramShapeCollection()
        {
            _links = new List<ShapeLink>(10);
        }

        public ShapeLink AddLink(DiagramShape startShape, int startHotPoint, DiagramShape endShape, int endHotPoint,
            DiagramLinkLineType type = DiagramLinkLineType.RightAngle, string text = null)
        {
            if (startShape == null)
                throw new ArgumentNullException("startShape");
            if (endShape == null)
                throw new ArgumentNullException("endShape");

            if (!this.Contains(startShape))
                throw new ArgumentException(SR.GetString("shape_not_found"));

            if (!this.Contains(endShape))
                throw new ArgumentException(SR.GetString("shape_not_found"));

            ShapeLink link = new ShapeLink(startShape, startHotPoint, endShape, endHotPoint, type);
            link.LinkLine.Text = text;

            this.Add(link.LinkLine);

            return link;
        }

        private List<ShapeLink> _links;

        public ReadOnlyCollection<ShapeLink> Links
        {
            get
            {
                return _links.AsReadOnly();
            }
        }

        public void DrawShapes(Graphics graphics)
        {
            DrawShapeArgs args = new DrawShapeArgs(graphics);

            foreach (DiagramShape shape in this)
            {
                shape.Draw(args);
            }
        }

        protected virtual void OnCollectionChanged(EventArgs e)
        {
            if (CollectionChanged != null)
                CollectionChanged(this, e);
        }

        protected override void InsertItem(int index, Dycox.Drawing.DiagramShape item)
        {
            if (item == null)
                throw new ArgumentNullException("item");

            base.InsertItem(index, item);

            OnCollectionChanged(EventArgs.Empty);
        }

        protected override void ClearItems()
        {
            base.ClearItems();
            _links.Clear();

            OnCollectionChanged(EventArgs.Empty);
        }

        protected override void RemoveItem(int index)
        {
            DiagramShape shape = this[index];
            base.RemoveItem(index);
            OnShapeRemoved(shape);
            OnCollectionChanged(EventArgs.Empty);
        }

        protected override void SetItem(int index, DiagramShape item)
        {
            DiagramShape shape = this[index];
            base.SetItem(index, item);
            OnShapeRemoved(shape);
            OnCollectionChanged(EventArgs.Empty);
        }

        private void OnShapeRemoved(DiagramShape shape)
        {
            int index = 0;

            foreach (var link in _links)
            {
                // 如果移除的形状是连接线，则移除相应的ShapeLink对象。
                if (shape == link.LinkLine)
                    break;

                if (link.Start.TargetShape == shape || link.End.TargetShape == shape)
                {
                    // 直接调用基类的方法是为了防止重入
                    base.RemoveItem(this.IndexOf(link.LinkLine));
                    break;
                }

                index++;
            }

            if (index < _links.Count)
                _links.RemoveAt(index);
        }
    }
}
